package fr.sedoo.rbv.geonetwork.request;

import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.binder.DigesterLoader;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.jdom2.Document;
import org.jdom2.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;

import fr.sedoo.rbv.geonetwork.config.GeonetworkConfig;
import fr.sedoo.rbv.geonetwork.domain.GeonetworkUser;
import fr.sedoo.rbv.geonetwork.request.csw.GeoSummaryModule;

public class GeoSummaryRequest extends AbstractCSWRequest
{
	private static Logger logger = LoggerFactory.getLogger(GeoSummaryRequest.class);
	public final static String DATASET_TYPE="dataset";
	public final static String EXPERIMENTAL_SITE_TYPE="experimentalsite";

	private List<GeoSummary> summaries = new ArrayList<GeoSummary>();
	private ArrayList<String> displayLanguages = new ArrayList<String>();

	private final int MAX_RECORDS = 1000;

	private String type;

	public GeoSummaryRequest(GeonetworkUser user)
	{
		super(user);

	}

	public GeoSummaryRequest(GeonetworkConfig config)
	{
		super(config);
	}

	public GeoSummaryRequest(GeonetworkUser user, String type)
	{
		this(user);
		this.type = type;
	}

	@Override
	public boolean execute() throws Exception
	{

		Element request = getLocateElement();
		String cswURL = getConfig().getCSWPublicationURL();
		PostMethod post = new PostMethod(cswURL);

		try
		{
			String postData = getString(new Document(request));
			post.setRequestEntity(new StringRequestEntity(postData, "application/xml", UTF8));

			String rawXml = executePostMethod(post);
			if (rawXml.length() > 0)
			{
				logger.debug(rawXml);
				rawXml = SummaryByIdRequest.adaptTranslationTag(rawXml, displayLanguages);
				DigesterLoader digesterLoader = DigesterLoader.newLoader(new GeoSummaryModule());
				Digester digester = digesterLoader.newDigester();
				digester.setValidating(false);

				ByteArrayInputStream inputStream = new ByteArrayInputStream(rawXml.getBytes());
				Reader reader = new InputStreamReader(inputStream,"UTF-8");
				InputSource is = new InputSource(reader);
				is.setEncoding("UTF-8");

				setSummaries((List<GeoSummary>) digester.parse(is));

				return true;
			} else
			{
				throw new Exception();
			}
		} catch (Exception e)
		{
			throw new Exception(e);
		} finally
		{
			post.releaseConnection();
		}

	}

	private Element getLocateElement()
	{
		Element getRecords = new Element("GetRecords", cswNamespace).setAttribute("service", "CSW").setAttribute("version", "2.0.2").setAttribute("resultType", "results")
				.setAttribute("outputSchema", "csw:IsoRecord").setAttribute("maxRecords", "" + MAX_RECORDS);
		Element query = new Element("Query", cswNamespace).setAttribute("typeNames", "gmd:MD_Metadata").setAttribute("elementnameStrategy", "context");
		getRecords.addContent(query);

		Element constraintElement = new Element("Constraint", cswNamespace).setAttribute("version", "1.1.0");
		Element filterElement = new Element("Filter", ogcNamespace);

		if (type.compareToIgnoreCase(DATASET_TYPE)==0)
		{

			Element propertyIsLikeElement = new Element("PropertyIsLike", ogcNamespace).setAttribute("singleChar", " ").setAttribute("escape", "\\\\").setAttribute("wildCard", "%");
			Element propertyNameElement = new Element("PropertyName", ogcNamespace).setText("Type");
			Element literalElement = new Element("Literal", ogcNamespace).setText(SearchRequest.DATASET);
			propertyIsLikeElement.addContent(propertyNameElement);
			propertyIsLikeElement.addContent(literalElement);
			filterElement.addContent(propertyIsLikeElement);
		}

		else if (type.compareToIgnoreCase(EXPERIMENTAL_SITE_TYPE)==0)
		{
			Element andElement = new Element(SearchCriteria.AND, ogcNamespace);

			Element propertyIsLikeElement = new Element("PropertyIsLike", ogcNamespace).setAttribute("singleChar", " ").setAttribute("escape", "\\\\").setAttribute("wildCard", "%");
			Element propertyNameElement = new Element("PropertyName", ogcNamespace).setText("Type");
			Element literalElement = new Element("Literal", ogcNamespace).setText(SearchRequest.SERIES);
			propertyIsLikeElement.addContent(propertyNameElement);
			propertyIsLikeElement.addContent(literalElement);

			Element propertyIsLikeElement2 = new Element("PropertyIsLike", ogcNamespace).setAttribute("singleChar", " ").setAttribute("escape", "\\\\").setAttribute("wildCard", "%");
			Element propertyNameElement2 = new Element("PropertyName", ogcNamespace).setText("AnyText");
			Element literalElement2 = new Element("Literal", ogcNamespace).setText(SearchRequest.EXPERIMENTAL_SITE_LEVEL_NAME);
			propertyIsLikeElement2.addContent(propertyNameElement2);
			propertyIsLikeElement2.addContent(literalElement2);

			andElement.addContent(propertyIsLikeElement);
			andElement.addContent(propertyIsLikeElement2);
			filterElement.addContent(andElement);
		}

		//		Element fileIdentifier = new Element("ElementName", cswNamespace).setText("/gmd:MD_Metadata/gmd:fileIdentifier");
		//		Element title = new Element("ElementName", cswNamespace).setText("/gmd:MD_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:citation/gmd:CI_Citation/gmd:title");
		//		Element box = new Element("ElementName", cswNamespace)
		//				.setText("/gmd:MD_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:extent/gmd:EX_Extent/gmd:geographicElement/gmd:EX_GeographicBoundingBox");
		//		Element resourceAbstract = new Element("ElementName", cswNamespace).setText("/gmd:MD_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:abstract");
		//		Element rbvExtent = new Element("ElementName", cswNamespace).setText("/gmd:MD_Metadata/rbv:rbvExtent");
		//		query.addContent(fileIdentifier);
		//		query.addContent(title);
		//		query.addContent(box);
		//		query.addContent(resourceAbstract);
		//		query.addContent(rbvExtent);

		Element all = new Element("ElementName", cswNamespace).setText("/gmd:MD_Metadata");
		query.addContent(all);
		constraintElement.addContent(filterElement);
		query.addContent(constraintElement);

		return getRecords;
	}

	public List<GeoSummary> getSummaries() {
		return summaries;
	}

	public void setSummaries(List<GeoSummary> summaries) {
		this.summaries = summaries;
	}

	public void setDisplayLanguages(ArrayList<String> displayLanguages) {
		this.displayLanguages = displayLanguages;
	}

}
